#pragma once

#include <map>
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
#include <opencv2/opencv.hpp>
#include <seeta/FaceDetector.h>
#include <seeta/FaceLandmarker.h>
#include <seeta/FaceRecognizer.h>
#include "handler.h"
#include "to.h"


namespace YQ {

using std::string;
using std::map;
using std::vector;
using std::shared_ptr;
using std::runtime_error;

using cv::Mat;
using cv::imread;
using cv::Rect;
using cv::ImreadModes;

using seeta::FaceDetector;
using seeta::FaceLandmarker;
using seeta::FaceRecognizer;
using seeta::ImageData;
using seeta::QualityLevel;
using seeta::QualityResult;


struct ExtractResult {
	SeetaFaceInfo face_info;
	vector<SeetaPointF> face_points;
	shared_ptr<float> features;
	int features_size;
};


/// @warning 图中无人脸时，xxxBiggestXxx会抛出std::runtime_error。
struct FaceExtractor final {
public:
	FaceExtractor();
	explicit FaceExtractor (shared_ptr<const ImageData>);
	
	SeetaFaceInfo getBiggestFace () noexcept (false);
	shared_ptr<ExtractResult> extractBiggestFaceInfo() noexcept (false);
	vector<SeetaFaceInfo>getFaces();
	vector<SeetaPointF> getFacePoints (const SeetaRect &face_rect);
	shared_ptr<float> getFaceFeatures (const vector<SeetaPointF> &face_points);
	int getExtractFeatureSize();
	void setImage (shared_ptr<const ImageData>);
	shared_ptr<FaceRecognizer> getRecognizer();
private:
	shared_ptr<const ImageData> img;
	shared_ptr<FaceDetector> detector;
	shared_ptr<FaceRecognizer> recognizer;
	shared_ptr<FaceLandmarker> marker;
};

struct QualityChecker final {
	QualityChecker() = delete;
public:
	QualityChecker (shared_ptr<const ImageData>, shared_ptr<const ExtractResult>);
	
	QualityResult getBrightnessQuality();
	QualityResult getClarityQuality();
	QualityResult getPoseQuality();
	QualityResult getResolutionQuality();
	QualityResult getIntergrityQuality();
	void setImage (shared_ptr<const ImageData>);
private:
	shared_ptr<const ImageData> img;
	shared_ptr<const ExtractResult> extract_result;
	shared_ptr<QualityOfBrightness> brightness_checker;
	shared_ptr<QualityOfClarity> clarity_checker;
	shared_ptr<QualityOfPoseEx> pose_checker;
	shared_ptr<QualityOfResolution> resolution_checker;
	shared_ptr<QualityOfIntegrity> integrity_checker;
};

}